package com.qianfeng.smartdevice.log.advices;

//
//                            _ooOoo_  
//                           o8888888o  
//                           88" . "88  
//                           (| -_- |)  
//                            O\ = /O  
//                        ____/`---'\____  
//                      .   ' \\| |// `.  
//                       / \\||| : |||// \  
//                     / _||||| -:- |||||- \  
//                       | | \\\ - /// | |  
//                     | \_| ''\---/'' | |  
//                      \ .-\__ `-` ___/-. /  
//                   ___`. .' /--.--\ `. . __  
//                ."" '< `.___\_<|>_/___.' >'"".  
//               | | : `- \`.;`\ _ /`;.`/ - ` : | |  
//                 \ \ `-. \_ __\ /__ _/ .-` / /  
//         ======`-.____`-.___\_____/___.-`____.-'======  
//                            `=---='  
//  
//         .............................................  
//                  佛祖镇楼                  BUG辟易  
//          佛曰:  
//                  写字楼里写字间，写字间里程序员；  
//                  程序人员写程序，又拿程序换酒钱。  
//                  酒醒只在网上坐，酒醉还来网下眠；  
//                  酒醉酒醒日复日，网上网下年复年。  
//                  但愿老死电脑间，不愿鞠躬老板前；  
//                  奔驰宝马贵者趣，公交自行程序员。  
//                  别人笑我忒疯癫，我笑自己命太贱；  
//  


import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.qianfeng.smartdevice.exceptions.MyBaseException;
import com.qianfeng.smartdevice.log.annotations.LogAnno;
import com.qianfeng.smartdevice.pojo.OperLog;
import com.qianfeng.smartdevice.utils.RequestUtils;
import com.qianfeng.smartdevice.utils.SecruitUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

/**
 * Created by Jackiechan on 2022/1/20/21:12
 *
 * @author Jackiechan
 * @version 1.0
 * @since 1.0
 */
@Aspect
@Component
public class LogAdvice {

    private ObjectMapper objectMapper;

    @Autowired
    public void setObjectMapper(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    @Pointcut("@annotation(com.qianfeng.smartdevice.log.annotations.LogAnno)")
    public void pointcut() {
    }

    @AfterReturning(value = "pointcut()",returning = "result")
    public void after(JoinPoint joinPoint, Object result) {
        OperLog operLog = new OperLog();
        try {
            operLog.setStatus(1L);
            operLog.setErrorMsg("200 OK");
            operLog.setJsonResult(objectMapper.writeValueAsString(result));
            addLog(joinPoint, operLog);
        }catch (Exception e){
           e.printStackTrace();
        }
    }




    @AfterThrowing(value = "pointcut()",throwing ="e" )
    public void afterThrowing(JoinPoint joinPoint, Throwable e) {
        OperLog operLog = new OperLog();
        operLog.setStatus(0L);
        if (e instanceof MyBaseException) {
            try {
                operLog.setErrorMsg(objectMapper.writeValueAsString(e ));

            } catch (JsonProcessingException ex) {
                ex.printStackTrace();
            }
        }else{
            operLog.setErrorMsg(e.getMessage());
        }
            addLog(joinPoint,operLog);
    }



    private void addLog(JoinPoint joinPoint, OperLog operLog){
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String ip = RequestUtils.getRemoteHost(request);
        Map<String, String> osAndBrowserInfo = RequestUtils.getOsAndBrowserInfo(request);
        String requestMethod = request.getMethod();
        operLog.setOperName(SecruitUtils.getUser().getUsername());

        CompletableFuture.runAsync(()->{
            MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
            String methodName = methodSignature.getName();//方法名
            operLog.setMethod(methodName);
            Object[] args = joinPoint.getArgs();
            if (args != null&& args.length>0) {
                try {
                    operLog.setOperParam(objectMapper.writeValueAsString(args));
                } catch (JsonProcessingException e) {
                    e.printStackTrace();
                }
            }
            Method method = methodSignature.getMethod();//当前正在执行的方法,这个方法上面一定有我们的注解,因为没有注解过不来
            LogAnno logAnno = method.getAnnotation(LogAnno.class);
            String title = logAnno.title();//标题
            int businessType = logAnno.businessType();
            operLog.setTitle(title);
            operLog.setBusinessType((long) businessType);
            operLog.setOperUrl(request.getRequestURI());
            operLog.setOperIp(ip);
            operLog.setRequestMethod(requestMethod);
            String os = osAndBrowserInfo.get("os");
            switch (os) {
                case "Android":
                case "IPhone":
                    operLog.setOperatorType(2l);
                    break;
                case "Windows":
                case "Mac":
                case "Linux":
                    operLog.setOperatorType(1l);
                    break;
                default:
                    operLog.setOperatorType(0l);
                    break;
            }
            String location = RequestUtils.getLocationByIp(ip);
            operLog.setOperLocation(location);
            operLog.setOperTime(new Date());
            System.err.println(operLog);
        });
    }

}
